package icegps.com.pingdj.map;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import icegps.com.pingdj.map.bean.MapStatus;
import icegps.com.pingdj.map.listener.OnMapEventListener;
import icegps.com.pingdj.map.listener.OnMapMultipleListener;
import icegps.com.pingdj.map.listener.TriggerToDraw;
import icegps.com.pingdj.map.thread.MapRunnable;
import icegps.com.pingdj.map.thread.ThreadPool;
import timber.log.Timber;


/**
 * Created by 111 on 2018/2/25.
 */

public class MapView extends SurfaceView implements SurfaceHolder.Callback {
    private MapStatus mapStatus;
    private SurfaceHolder holder;
    private GestureDetector gestureDetector;
    private ScaleGestureDetector scaleGestureDetector;
    private TriggerToDraw triggerToDraw;
    private OnMapEventListener onMapEventListener;
    private Canvas canvas;
    private boolean isIdle;
    private volatile boolean drawFlag;
    private float doubleTapMultiple = 2.0f;
    private int count = 100;
    private int sleep = 1;
    private OnMapMultipleListener onMapMultipleListener;

    public MapView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        isIdle = true;
        gestureDetector = new GestureDetector(getContext(), simpleOnGestureListener);
        scaleGestureDetector = new ScaleGestureDetector(getContext(), onScaleGestureListener);
        mapStatus = new MapStatus();
        holder = getHolder();
        holder.addCallback(MapView.this);

    }

    public MapStatus getMapStatus() {
        return mapStatus;
    }

    private synchronized void draw() {
        try {
            canvas = holder.lockCanvas();
            if (onMapMultipleListener != null) {
                onMapMultipleListener.onMultiple(mapStatus.getMultiple());
            }
            canvas.drawColor(Color.parseColor("#F3EEE8"));
            if (triggerToDraw != null) {
                triggerToDraw.trigger1(canvas);
            }
            //平移
            canvas.translate(mapStatus.getSumTx(), mapStatus.getSumTy());
            if (triggerToDraw != null) {
                triggerToDraw.trigger2(canvas);
            }
            //缩放
            canvas.scale(mapStatus.getMultiple(), mapStatus.getMultiple(), mapStatus.getMx(), mapStatus.getMy());
            if (triggerToDraw != null) {
                triggerToDraw.trigger3(canvas);
            }
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            try {
                holder.unlockCanvasAndPost(canvas);
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //双击\滑动
        gestureDetector.onTouchEvent(event);
        //缩放
        if (event.getPointerCount() == 2) {
            scaleGestureDetector.onTouchEvent(event);
        }

        if (event.getAction() == MotionEvent.ACTION_UP) {
            if (onMapEventListener != null) {
                onMapEventListener.onUpEvent();
            }
        }
        return true;
    }

    GestureDetector.SimpleOnGestureListener simpleOnGestureListener = new GestureDetector.SimpleOnGestureListener() {

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            if (isIdle) {
                isIdle = false;
                mapStatus.setTx(mapStatus.getTx() - distanceX);
                mapStatus.setTy(mapStatus.getTy() - distanceY);
                isIdle = true;
            }
            return super.onScroll(e1, e2, distanceX, distanceY);
        }

        @Override
        public boolean onDoubleTap(MotionEvent e) {
            animaScale(e.getX(), e.getY(), doubleTapMultiple);
            return super.onDoubleTap(e);
        }
    };

        public void animaScale(float x, float y, float multiple) {
            if (isIdle) {
                isIdle = false;
                float finalMultiple = mapStatus.getMultiple() * multiple;
                if (finalMultiple < 1.0f) {
                    finalMultiple = 1.0f;
                    multiple = finalMultiple / mapStatus.getMultiple();
                } else if (finalMultiple > 100f) {
                    finalMultiple = 100f;
                    multiple = finalMultiple / mapStatus.getMultiple();
                }
                //双击放大
                float px = (x - (mapStatus.getTx()));
                float py = (y - (mapStatus.getTy()));
                final float sumPx = px * multiple - px;
                final float sumPy = py * multiple - py;
                final float sum = finalMultiple - mapStatus.getMultiple();

                ThreadPool.getInstance().executeFixed(new MapRunnable() {
                    @Override
                    public void run() {
                        super.run();
                        for (int i = 1; i <= count; i++) {
                            SystemClock.sleep(sleep);
                            scale(
                                    mapStatus.getTx() - sumPx / count,
                                    mapStatus.getTy() - sumPy / count,
                                    mapStatus.getMultiple() + sum / count);
                        }
                        isIdle = true;
                        if (onMapEventListener != null) {
                            onMapEventListener.onScaleEnd();
                        }
                    }

                    @Override
                    protected String threadName() {
                        return "缩放线程";
                    }
                });
            }
        }

    ScaleGestureDetector.OnScaleGestureListener onScaleGestureListener = new ScaleGestureDetector.OnScaleGestureListener() {

        float focusX;
        float focusY;
        float tx;
        float ty;
        float multiple;

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            //手势缩放
            if (isIdle) {
                isIdle = false;
                if (focusX == 0 && focusY == 0) {
                    focusX = detector.getFocusX();
                    focusY = detector.getFocusY();
                }
                float scaleFactor = detector.getScaleFactor();
                float multiple = this.multiple * scaleFactor;

                float px = (focusX - tx);
                float py = (focusY - ty);

                if (multiple < 1.0f) {
                    multiple = 1.0f;
                    scaleFactor = multiple / this.multiple;
                } else if (multiple > 100f) {
                    multiple = 100f;
                    scaleFactor = multiple / this.multiple;
                }

                float tx = this.tx - (px * scaleFactor - px);

                float ty = this.ty - (py * scaleFactor - py);

                scale(tx, ty, multiple);

                isIdle = true;
            }
            return false;
        }

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            //手势缩放开始时 取一次基准值
            tx = mapStatus.getTx();
            ty = mapStatus.getTy();
            multiple = mapStatus.getMultiple();
            return true;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
            focusX = 0;
            focusY = 0;
        }
    };

    private void scale(float tx, float ty, float multiple) {
        mapStatus.setMultiple(multiple);
        mapStatus.setTx(tx);
        mapStatus.setTy(ty);
    }

    public void addOnMapEventListener(OnMapEventListener onMapEventListener) {
        this.onMapEventListener = onMapEventListener;
    }

    class DrawRunnable implements Runnable {
        @Override
        public void run() {
            while (drawFlag) {
                Timber.v("线程日志--->" + "map_draw_thread");
                SystemClock.sleep(1);
                draw();
            }
        }
    }

    public void addTriggerToDraw(TriggerToDraw triggerToDraw) {
        this.triggerToDraw = triggerToDraw;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        drawFlag = true;
        ThreadPool.getInstance().executeSingle(new DrawRunnable());
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        drawFlag = false;
    }

    public void setOnMapMultipleListener(OnMapMultipleListener onMapMultipleListener) {
        this.onMapMultipleListener = onMapMultipleListener;
    }
}
